home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1997 April
/
EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso
/
EARCD
/
comm
/
term
/
Sterm.lha
/
sterm
/
sterm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-12-20
|
19KB
|
587 lines
/* STerm 1.0 -- © 1995 Dominique Lorre
*
* This was planned to be a very small terminal program (Small Term)
* that I developped because a lack of place on my A600 disk
* but it happened that I had to make it work with SAD (SAD Term).
* Other possibilities are SerialTerm 8->, SmartTerm ;-),...
*
* This software is in the Public Domain. You can modify it but in
* this case you should find a new name for the program.
*/
#include <exec/types.h>
#include <devices/console.h>
#include <devices/serial.h>
#include <string.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <clib/alib_protos.h>
static struct MsgPort *SerialPort, *conport ;
static struct IOExtSer *ReadIO, *WriteIO ;
static LONG Error ;
static ULONG SerSig ;
static ULONG ConSig ;
static ULONG WinSig ;
static ULONG signal ;
static struct FileHandle *fh ;
static UBYTE SerBuf[512] ;
static UBYTE ConBuf[512] ;
static BOOL fin=FALSE ;
static BPTR msgout ;
static struct Window *win ;
static struct IOStdReq *conreq, *outreq ;
static struct IntuiMessage *imsg ;
/* Command Datas are here */
static LONG hlen = 0, alen = 0 ;
static BOOL RawMode = TRUE ;
static LONG HexMode = 0 ;
/* SAD Datas are here */
static LONG length = 0 ;
static BOOL SADAsk = FALSE ;
static BOOL SADV39 = FALSE ;
static UBYTE ResetCmd[6] = { 0xAF, 0x10, 0xFF, 0xFF, 0xFF, 0xFF } ;
static UBYTE AbortCmd[6] = { 0xAF, 0x08, 0x00, 0x00, 0x00, 0x00 } ;
static UBYTE ReadWordCmd[6] = { 0xAF, 0x05, 0x00, 0xF8, 0x00, 0x00 } ;
static LONG rate[8] = {
110, 300, 1200, 2400, 4800, 9600, 19200, 31250
};
static UBYTE srate[8][6] = {
"110", "300", "1200", "2400", "4800", "9600", "19200", "31250"
};
/* Functions Prototypes */
BOOL InitDevs(void) ;
BOOL CloseDevs(WORD) ;
BOOL InitConsole(void) ;
BOOL CloseConsole(WORD) ;
BOOL SADCheckVersion(void) ;
void SADAbort(void) ;
void SADReset(void) ;
void SADSendCmd(STRPTR cmd, LONG len) ;
BOOL SADAckCmd(UBYTE ack) ;
void ConOut(STRPTR msg) ;
void SetBaudRate(long Baud) ;
void DisplayHelp(void) ;
void SendCom(STRPTR s) ;
void main(void)
{
struct IOExtSer *srep ;
struct IOStdReq *crep ;
if (InitDevs()) {
if (InitConsole()) {
do {
signal = Wait(SerSig|ConSig|WinSig) ;
/* No class check because only IDCMP_CLOSEWINDOW here */
if (signal & WinSig) {
while (imsg = (struct IntuiMessage *)GetMsg(win->UserPort)) {
ReplyMsg((struct Message *)imsg) ;
fin = TRUE ;
}
}
/* serial stuff */
if (signal & SerSig) {
while (srep = (struct IOExtSer *)GetMsg(SerialPort)) {
/* Here we check for SAD[?|!|¿] commands */
if (!srep->IOSer.io_Error && !SADAsk) {
if (length == 3) {
if (SerBuf[0] == '!' || SerBuf[0] == '?' ||
SerBuf[0] == 0xBF) {
SADAsk = TRUE ;
length = 0 ;
}
else
length = 0 ;
}
if (!RawMode) {
if (length == 2)
length = (SerBuf[0] == 'D')?3:0 ;
if (length == 1)
length = (SerBuf[0] == 'A')?2:0 ;
if (length == 0)
length = (SerBuf[0] == 'S')?1:0 ;
if (hlen == 2) {
if ((SerBuf[0] | 0x20) == 'x') {
HexMode = 1 ;
ConOut("HexMode set.\n") ;
}
hlen = 0 ;
}
if (hlen == 1)
hlen = ((SerBuf[0] | 0x20) == 'e')?2:0;
if (hlen == 0)
hlen = ((SerBuf[0] | 0x20) == 'h')?1:0;
if (alen == 2) {
if ((SerBuf[0] | 0x20) == 'c') {
HexMode = 0 ;
ConOut("HexMode unset.\n") ;
}
alen = 0 ;
}
if (alen == 1)
alen = ((SerBuf[0] | 0x20) == 's')?2:0;
if (alen == 0)
alen = ((SerBuf[0] | 0x20) == 'a')?1:0;
if (alen == 2) {
if ((SerBuf[0] | 0x20) == 'h') {
HexMode = 2 ;
ConOut("Semi HexMode set.\n") ;
}
alen = 0 ;
}
if (alen == 1)
alen = ((SerBuf[0] | 0x20) == 'e')?2:0;
if (alen == 0)
alen = ((SerBuf[0] | 0x20) == 's')?1:0;
}
SendCom(SerBuf) ;
if (SADAsk) {
ConOut(" command received.\nPlease quit STerm and launch Wack TARGET 0 command.\nPress 'R' key to reset computer.\nPress any other key to abort\n") ;
}
}
ReadIO->IOSer.io_Command = CMD_READ;
ReadIO->IOSer.io_Data = (APTR)SerBuf;
ReadIO->IOSer.io_Length = 1;
SendIO((struct IORequest *)ReadIO);
}
}
/* Console stuff */
if (signal & ConSig) {
while (crep = (struct IOStdReq *)GetMsg(conport)) {
ConBuf[crep->io_Actual] = '\0' ;
if (!crep->io_Error) {
if (SADAsk) {
SADAsk = FALSE ;
if (!CheckIO((struct IORequest *)ReadIO))
AbortIO((struct IORequest *)ReadIO) ;
WaitIO((struct IORequest *)ReadIO) ;
/* ['r', 'R'] means Reset */
if ((ConBuf[0] | 0x20) == 'r')
SADReset() ;
else
SADAbort() ;
ReadIO->IOSer.io_Command = CMD_READ;
ReadIO->IOSer.io_Data = (APTR)SerBuf;
ReadIO->IOSer.io_Length = 1;
SendIO((struct IORequest *)ReadIO);
}
if (ConBuf[0] == 0x9B) { /* CSI: do special work */
if (ConBuf[2] == '~') {
if (ConBuf[1] == 0x3F)
DisplayHelp() ;
else if (ConBuf[1] >= 0x30 &&
ConBuf[1] <= 0x37) {
SetBaudRate(ConBuf[1]-0x30) ;
}
else if (ConBuf[1] == 0x38) {
if (HexMode == 2) {
ConOut("HexMode unset.\n") ;
HexMode = 0 ;
}
else if (HexMode == 0) {
ConOut("HexMode set.\n") ;
HexMode = 1 ;
}
else {
ConOut("Semi-HexMode set.\n") ;
HexMode = 2 ;
}
}
else if (ConBuf[1] == 0x39) {
if (RawMode) {
ConOut("RawMode unset.\n") ;
RawMode = FALSE ;
}
else {
ConOut("RawMode set.\n") ;
RawMode = TRUE ;
}
}
}
}
ConBuf[crep->io_Actual] = '\0' ;
WriteIO->IOSer.io_Command = CMD_WRITE;
WriteIO->IOSer.io_Data = (APTR)ConBuf;
WriteIO->IOSer.io_Length = strlen(ConBuf);
DoIO((struct IORequest *)WriteIO);
Write(msgout, ConBuf, strlen(ConBuf)) ;
conreq->io_Command = CMD_READ;
conreq->io_Data = (APTR)ConBuf;
conreq->io_Length = 512;
SendIO((struct IORequest *)conreq);
}
}
}
} while (!fin) ;
CloseConsole(0) ;
}
CloseDevs(0) ;
}
}
/*
* InitDevs
* Alloc serial resources
* return TRUE for success
*/
BOOL InitDevs(VOID)
{
if (SerialPort = (struct MsgPort *)CreateMsgPort()) {
SerSig = (1L << SerialPort->mp_SigBit);
}
else
return CloseDevs(1);
if ((ReadIO = (struct IOExtSer *)
CreateIORequest((struct MsgPort *)SerialPort, sizeof(struct IOExtSer))) == NULL)
return CloseDevs(2);
ReadIO->io_SerFlags = SERF_SHARED;
if (Error = OpenDevice(SERIALNAME, 0, (struct IORequest *)ReadIO, 0))
return CloseDevs(3);
if ((WriteIO = (struct IOExtSer *)
CreateIORequest((struct MsgPort *)SerialPort, sizeof(struct IOExtSer))) == NULL)
return CloseDevs(4);
CopyMem(ReadIO, WriteIO, sizeof(struct IOExtSer)) ;
ReadIO->IOSer.io_Command = CMD_READ; /* Start reading serial */
ReadIO->IOSer.io_Data = (APTR)SerBuf;
ReadIO->IOSer.io_Length = 1;
SendIO((struct IORequest *)ReadIO);
return TRUE;
}
/*
* CloseDevs
* Frees serial resources
* return TRUE if called with level = 0 (no problem)
*/
BOOL CloseDevs(WORD level)
{
if (level)
Printf("devs:%ld\n", level);
switch (level) {
case 0:
DeleteIORequest((struct IORequest *)WriteIO) ;
case 4:
CloseDevice((struct IORequest *)ReadIO);
case 3:
DeleteIORequest((struct IORequest *)ReadIO);
case 2:
DeleteMsgPort(SerialPort);
case 1:
return (BOOL)(level?FALSE:TRUE);
}
}
/*
* InitConsole
* Alloc console structures
* return TRUE for success
*/
BOOL InitConsole(VOID)
{
STRPTR msgtitle = "CON:20/170/600/30/Echo Console" ;
msgout = Open(msgtitle, MODE_OLDFILE) ;
if (!msgout)
return CloseConsole(1) ;
win = OpenWindowTags(NULL,
WA_Left, 20,
WA_Top, 20,
WA_Width, 600,
WA_Height, 140,
WA_MaxWidth, 640,
WA_MaxHeight, 200,
WA_Title, "STerm V1.0 ©1994, Dominique Lorre -- Help key helps.",
WA_CloseGadget, TRUE,
WA_SizeGadget, TRUE,
WA_DepthGadget, TRUE,
WA_DragBar, TRUE,
WA_Activate, TRUE,
WA_SimpleRefresh, TRUE,
WA_IDCMP, IDCMP_CLOSEWINDOW,
TAG_DONE) ;
if (!win)
return CloseConsole(2) ;
WinSig = 1 << win->UserPort->mp_SigBit ;
conport = CreateMsgPort() ;
if (!conport)
return CloseConsole(3) ;
ConSig = 1 << conport->mp_SigBit ;
conreq = CreateStdIO(conport) ;
if (!conreq)
return CloseConsole(4) ;
outreq = CreateStdIO(conport) ;
if (!outreq)
return CloseConsole(5) ;
conreq->io_Data = win ;
Error = OpenDevice("console.device", 3, (struct IORequest *)conreq, 0) ;
if (Error)
return CloseConsole(6) ;
*outreq = *conreq ;
conreq->io_Command = CMD_READ; /* Starts reading console */
conreq->io_Data = (APTR)ConBuf;
conreq->io_Length = 512;
SendIO((struct IORequest *)conreq);
return TRUE ;
}
/*
* CloseConsole
* Frees console structures
* return TRUE if called with level = 0 (no problem)
*/
BOOL CloseConsole(WORD level)
{
if (level)
Printf("console : %ld\n", level) ;
switch (level) {
case 0:
CloseDevice((struct IORequest *)conreq) ;
case 6:
DeleteStdIO(outreq) ;
case 5:
DeleteStdIO(conreq) ;
case 4:
DeleteMsgPort(conport) ;
case 3:
CloseWindow(win) ;
case 2:
Close(msgout) ;
case 1:
return (BOOL)(level?FALSE:TRUE) ;
}
}
/*
* SADCheckVersion
* Checks if SAD is running on V39 or V40+
* return TRUE for success
*/
BOOL SADCheckVersion(void)
{
BOOL acked = FALSE ;
long i, length ;
SADSendCmd(ReadWordCmd, 6) ;
ReadIO->IOSer.io_Command = SDCMD_QUERY ;
DoIO((struct IORequest *)ReadIO) ;
length = ReadIO->IOSer.io_Actual ;
if (!ReadIO->IOSer.io_Error) {
ReadIO->IOSer.io_Command = CMD_READ;
ReadIO->IOSer.io_Data = (APTR)SerBuf;
ReadIO->IOSer.io_Length = length;
DoIO((struct IORequest *)ReadIO);
}
/* This is a "defensive programming" loop. SAD seems to clear the
serial buffers before replying.
*/
if (!ReadIO->IOSer.io_Error) {
for (i=0; i<length-1 && !acked ; i++) {
acked = SerBuf[i] == 0x00 &&
(SerBuf[i+1] == 0x05 || SerBuf[i+1] == 0x06) ;
}
}
if (acked) {
SADV39 = (SerBuf[i] == 0x06) ;
}
else
ConOut("Unable to contact SAD: SAD Link lost\n") ;
return acked ;
}
/*
* SADReset
* Send Reset Cmd to SAD
*/
void SADReset(void)
{
UBYTE cn ;
if (SADCheckVersion()) {
cn = SADV39?0x0F:0x10 ;
ResetCmd[1] = cn ;
SADSendCmd(ResetCmd, 6) ; /* Unable to check ack here */
ConOut("Target Computer should be rebooting now ...\n") ;
}
}
/*
* SADAbort
* Sends Abort Cmd to SAD
*/
void SADAbort(void)
{
UBYTE cn ;
if (SADCheckVersion()) {
cn = SADV39?0x07:0x08 ;
AbortCmd[1] = cn ;
SADSendCmd(AbortCmd, 6) ;
if (!SADAckCmd(0x08))
ConOut("Unable to Abort: SAD Link lost\n") ;
else
ConOut("Target Computer now has regained control...\n") ;
}
}
/*
* SADSendCmd
* Sends command to serial with a little delay to allow ack checking
*/
void SADSendCmd(STRPTR cmd, LONG len)
{
WriteIO->IOSer.io_Command = CMD_WRITE ;
WriteIO->IOSer.io_Data = (APTR)cmd;
WriteIO->IOSer.io_Length = len ;
DoIO((struct IORequest *)WriteIO) ;
Delay(10) ; /* Give time to Time */
}
/*
* SADAckCmd
* Checks if command identified by ack has succeeded
* returns TRUE for success
*/
BOOL SADAckCmd(UBYTE ack)
{
BOOL acked = FALSE ;
long i, length ;
ReadIO->IOSer.io_Command = SDCMD_QUERY ; /* How many bytes in serial ? */
DoIO((struct IORequest *)ReadIO) ;
length = ReadIO->IOSer.io_Actual ;
if (!ReadIO->IOSer.io_Error) {
ReadIO->IOSer.io_Command = CMD_READ; /* Read them */
ReadIO->IOSer.io_Data = (APTR)SerBuf;
ReadIO->IOSer.io_Length = length;
DoIO((struct IORequest *)ReadIO);
}
if (!ReadIO->IOSer.io_Error) {
/* This is a "defensive programming" loop. SAD seems to clear the
serial buffers before replying.
*/
for (i=0; i<length-1 && !acked ; i++) { /* Check if ack is inside */
acked = SerBuf[i] == 0x00 && (SerBuf[i+1] == ack) ;
}
}
return acked ;
}
/*
* ConOut
* Sends msg to Serial Console
*/
void ConOut(STRPTR msg)
{
static UBYTE selon[5] = {0x9B, ';', '3', '3', 'm' };
static UBYTE seloff[5] = {0x9B, ';', '3', '1', 'm' };
outreq->io_Command = CMD_WRITE;
outreq->io_Data = selon ;
outreq->io_Length = 5 ;
DoIO((struct IORequest *)outreq);
outreq->io_Data = msg ;
outreq->io_Length = strlen(msg) ;
DoIO((struct IORequest *)outreq);
outreq->io_Data = seloff;
outreq->io_Length = 5 ;
DoIO((struct IORequest *)outreq);
}
void SetBaudRate(long Baud)
{
WriteIO->IOSer.io_Command = CMD_RESET;
DoIO((struct IORequest *)WriteIO);
WriteIO->IOSer.io_Command = SDCMD_SETPARAMS;
WriteIO->io_SerFlags = SERF_RAD_BOOGIE | SERF_SHARED;
WriteIO->io_ExtFlags = 0;
WriteIO->io_Baud = rate[Baud];
WriteIO->io_RBufLen = 512;
WriteIO->io_ReadLen = 8;
WriteIO->io_WriteLen = 8;
WriteIO->io_StopBits = 1;
DoIO((struct IORequest *)WriteIO);
ConOut("Rate set to ") ;
ConOut(srate[Baud]) ;
ConOut(" bauds.\n") ;
}
void DisplayHelp(void)
{
ConOut("STerm V1.0, ©1995, Dominique Lorre\n") ;
ConOut("Click window close gadget to quit.\n") ;
ConOut("Serial rates :\n") ;
ConOut("\t F1: 110 bauds\n") ;
ConOut("\t F2: 300 bauds\n") ;
ConOut("\t F3: 1200 bauds\n") ;
ConOut("\t F4: 2400 bauds\n") ;
ConOut("\t F5: 4800 bauds\n") ;
ConOut("\t F6: 9600 bauds\n") ;
ConOut("\t F7: 19200 bauds\n") ;
ConOut("\t F8: 31250 bauds\n") ;
ConOut("\t F9: Toggle Hex Mode\n") ;
ConOut("\tF10: Toggle Raw Mode\n") ;
}
void SendCom(STRPTR s)
{
static char hexa[3] = {'$', '0', '0'};
outreq->io_Command = CMD_WRITE;
if (!HexMode || ((HexMode == 2) && s[0] >= 0x20 && s[0] < 0x7F)) {
outreq->io_Data = (APTR)s ;
outreq->io_Length = 1;
DoIO((struct IORequest *)outreq);
}
else {
hexa[1] = (s[0] & 0xF0) >> 4 ;
hexa[2] = s[0] & 0x0F ;
if (hexa[1] > 9)
hexa[1] += 'A' - 10 ;
else
hexa[1] += '0' ;
if (hexa[2] > 9)
hexa[2] += 'A' - 10 ;
else
hexa[2] += '0' ;
outreq->io_Data = (APTR)hexa ;
outreq->io_Length = 3 ;
DoIO((struct IORequest *)outreq);
}
}